package com.hc.testaudio.deletea.util.forurier;

import com.yc.yclibx.comment.YcCalculator;

/**
 * 原始的傅里叶变换
 * 公式
 * Xn = ∑(下界n=0,上界N-1)[x[n]cos(2πkn/N)] - j*∑(下界n=0,上界N-1)[x[n]sin(2πkn/N)]
 */
public class FdtUtil {
    public static float[] fdt(int[] data) {
        int N = data.length;
        float[] reals = new float[data.length];
        float[] images = new float[data.length];
        for (int i = 0; i < N; i++) {
            float real = 0f;
            float image = 0f;
            for (int j = 0; j < N; j++) {
                real = real + getReal(data[j], i, j, N);
                image = image + getImage(data[j], i, j, N);
            }
            reals[i] = (float) YcCalculator.roundOff(real, 2);
            reals[i] = (float) YcCalculator.roundOff(image, 2);
        }
        return images;
    }

    public static float[] fdt(byte[] data) {
        int N = data.length;
        float[] resultReal = new float[data.length];
        float[] resultImage = new float[data.length];
        for (int i = 0; i < N; i++) {
            float real = 0f;
            float image = 0f;
            for (int j = 0; j < N; j++) {
                real = real + getReal(data[j], i, j, N);
                image = image + getImage(data[j], i, j, N);
            }
            resultReal[i] = (float) YcCalculator.roundOff(real, 2);
            resultImage[i] = (float) YcCalculator.roundOff(image, 2);
        }
        float[] result = new float[data.length];//傅里叶变换只有前面一半数据有用
        result[0] = resultReal[0];          //DC直流分量 ；第一个数据没有虚部的
        result[1] = resultReal[data.length / 2]; //Nyquist 奈奎斯特频率；
        for (int i = 2; i < data.length; i += 2) {    //FFT结果显示
            result[i] = resultReal[i / 2];
            result[i + 1] = resultImage[i / 2];
        }
        for (int i = 0; i < data.length; i++) {    //FFT结果显示
            System.out.println(resultReal[i] + " + j " + resultImage[i]);
        }
        return result;
    }
    //    public static List<Complex> fdt(byte[] data) {
//        int N = data.length;
//        List<Complex> dataList = new ArrayList<>();
//        for (int i = 0; i < N; i++) {
//            double real = 0;
//            double image = 0;
//            for (int j = 0; j < N; j++) {
//                real = real + getReal(data[j], i, j, N);
//                image = image + getImage(data[j], i, j, N);
//            }
//            dataList.add(new Complex(YcCalculator.roundOff(real, 2), YcCalculator.roundOff(image, 2)));
//        }
//        return dataList;
//    }
//    public static List<Complex> fdtTemp(int[] data) {
//        int N = data.length;
////        List<Complex> dataList = new ArrayList<>();
//        int n, k;
//        double[] dft_out_re = new double[N];
//        double[] dft_out_im = new double[N];
//        double[] dft_one_re = new double[N];
//        double[] dft_one_im = new double[N];
//        double[] amp = new double[8000];
//        for (k = 0; k < N; k++) {
//            for (n = 0; n < N; n++) {
////                s = 0.6 * Math.sin(n * Math.PI * 100) + 0.6 * Math.sin(n * Math.PI * 1000);
//                dft_one_re[n] = Math.cos(2 * Math.PI / N * n * k);
//                dft_one_im[n] = Math.sin(2 * Math.PI / N * n * k);
//                dft_out_re[k] += dft_one_re[n];
//                dft_out_im[k] += dft_one_im[n];
//            }
//            dataList.add(new Complex(YcCalculator.roundOff(dft_out_re[k], 2), YcCalculator.roundOff(dft_out_im[k], 2)));
//        }
//        return dataList;
//    }
//
//    public static List<Complex> fdt(byte[] data) {
//        int N = data.length;
//        List<Complex> dataList = new ArrayList<>();
//        for (int i = 0; i < N; i++) {
//            int real = 0;
//            int image = 0;
//            for (int j = 0; j < N; j++) {
//                real += getReal(data[j], i, j, N);
//                image += getImage(data[j], i, j, N);
//            }
//            dataList.add(new Complex(real, image));
//        }
//        return dataList;
//    }

    public static float getReal(float item, int k, int n, int N) {
        return (float) (item * Math.cos(2 * Math.PI * k * n / N));
    }

    public static float getImage(float item, int k, int n, int N) {
        return (float) (-1 * item * Math.sin(2 * Math.PI * k * n / N));
    }

}
